package com.grandtech.insurance.common.utils.collect;

import com.grandtech.insurance.common.db.jdbc.sql.ReflectUtil;
import com.grandtech.insurance.common.utils.ObjectUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @param <T>
 */
public class CollectUnion<T> {

    private Map<String, T> resultMap;

    private Map<String, Object> attrMap;

    private Map<String, Object> removeMap;

    private String[] mergeWords;

    private List<T> list1;

    private List<T> list2;

    /**
     * @param list1      基准集合
     * @param list2      标准集合
     * @param mergeWords
     */
    public CollectUnion(List<T> list1, List<T> list2, Map<String, Object> attrMap, Map<String, Object> removeMap, String... mergeWords) {
        this.list1 = list1;
        this.list2 = list2;
        if (mergeWords == null || mergeWords.length == 0) new Throwable("mergeWords is NULL");
        this.mergeWords = mergeWords;
        this.attrMap = attrMap;
        this.removeMap = removeMap;
        this.resultMap = new HashMap<>();
    }

    public CollectUnion merge() {
        if (list1 != null) {
            StringBuffer key;
            T t;
            for (int i = 0; i < list1.size(); i++) {
                key = new StringBuffer();
                t = list1.get(i);
                if (t == null) continue;
                for (int j = 0; j < mergeWords.length; j++) {
                    String val = ReflectUtil.getValByNumberVar(t, mergeWords[j]);
                    key.append(val);
                }
                if (removeMap != null) {
                    boolean isAddToRes = true;
                    for (String removeKey : removeMap.keySet()) {
                        Object removeVal = removeMap.get(removeKey);
                        Object val = ReflectUtil.getValByNumberVar(t, removeKey);
                        isAddToRes = !ObjectUtil.baseTypeIsEqual(val, removeVal, true);
                        if (!isAddToRes) break;
                    }
                    if (isAddToRes) {
                        resultMap.put(key.toString(), t);
                    } else {
                        resultMap.remove(key.toString());
                    }
                }
            }
        }
        if (list2 != null) {
            StringBuffer key;
            T t;
            for (int i = 0; i < list2.size(); i++) {
                key = new StringBuffer();
                t = list2.get(i);
                if (t == null) continue;
                for (int j = 0; j < mergeWords.length; j++) {
                    String val = ReflectUtil.getValByNumberVar(t, mergeWords[j]);
                    key.append(val);
                }
                boolean isAddToRes = true;
                for (String removeKey : removeMap.keySet()) {
                    Object removeVal = removeMap.get(removeKey);
                    Object val = ReflectUtil.getValByNumberVar(t, removeKey);
                    isAddToRes = !ObjectUtil.baseTypeIsEqual(val, removeVal, true);
                    if (!isAddToRes) break;
                }
                if (isAddToRes) {
                    if (attrMap != null) {
                        for (String attrKey : attrMap.keySet()) {
                            Object attrVal = attrMap.get(attrKey);
                            ReflectUtil.setFieldValue(t, attrKey, attrVal);
                        }
                    }
                    resultMap.put(key.toString(), t);
                } else {
                    resultMap.remove(key.toString());
                }
            }
        }
        return this;
    }

    public List<T> toList() {
        if (resultMap == null) return null;
        List<T> list = new ArrayList<>();
        T t;
        for (String key : resultMap.keySet()) {
            t = resultMap.get(key);
            list.add(t);
        }
        return list;
    }
}
